﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace crc32
{
    class Program
    {
        static void Main(string[] args)
        {
            var crcArgs = new CrcArgs();
            crcArgs.Parse(args);
            if (string.IsNullOrEmpty(crcArgs.Directory))
            {
                Console.WriteLine("Please enter directory to scan [g:\\comic downloads]: ");
                var input = Console.ReadLine();
                if (string.IsNullOrEmpty(input))
                {
                    input = @"g:\comic downloads";
                }
                crcArgs.Directory = input;
            }
            var files = Directory.EnumerateFiles(crcArgs.Directory, "*.sfv");
            foreach (var file in files)
            {
                var crcData = SfvParser.Parse(File.Open(file, FileMode.Open));
                foreach (var data in crcData)
                {
                    try
                    {
                        string destDirectoryName;
                        using (var fs = File.Open(Path.Combine(crcArgs.Directory, data.FileName), FileMode.Open))
                        {
                            var crc32 = new Crc32();
                            var hash = string.Empty;
                            hash = crc32.ComputeHash(fs).Aggregate(hash, (current, b) => current + b.ToString("x2").ToLower());
                            if (hash.ToLower() == data.Crc.ToLower())
                            {
                                ConsolePlus.WriteLineGreen("{0} {1} OK", data.FileName, data.Crc);
                                destDirectoryName = "passed";
                            }
                            else
                            {
                                ConsolePlus.WriteLineRed("{0} {1} Not OK", data.FileName, data.Crc);
                                destDirectoryName = "failed";
                            }
                        }
                        if (crcArgs.MoveFiles)
                        {
                            MoveFile(crcArgs.Directory, data.FileName, destDirectoryName);
                        }
                    }
                    catch (FileNotFoundException)
                    {
                        ConsolePlus.WriteLineYellow("{0} {1} NOT FOUND", data.FileName, data.Crc);
                    }
                    catch (Exception e)
                    {
                        var oldBackColor = Console.BackgroundColor;
                        Console.BackgroundColor = ConsoleColor.Red;
                        ConsolePlus.WriteLineBlack("{0} {1} ERROR {2}", data.FileName, data.Crc, e.Message);
                        Console.BackgroundColor = oldBackColor;
                    }
                }
            }

            if (crcArgs.TestFiles)
            {
                var passedDirectory = Path.Combine(crcArgs.Directory, "passed");
                if (Directory.Exists(passedDirectory))
                {
                    TestFiles(passedDirectory);
                }
                else
                {
                    ConsolePlus.WriteLineRed("directory {0} does not exist", passedDirectory);
                }
                var directory = crcArgs.Directory;
                TestFiles(directory);
            }
            if (Debugger.IsAttached)
            {
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }

        private static void TestFiles(string directory)
        {
            var testfiles = Directory.EnumerateFiles(directory);
            foreach (var testfile in testfiles)
            {
                var testFileInfo = new FileInfo(testfile);
                if (testFileInfo.Extension != "rar" && testFileInfo.Extension != "zip" &&
                    testFileInfo.Extension != "cbz" && testFileInfo.Extension != "cbr")
                {
                    continue;
                }
                var infoProcess = new Process
                                      {
                                          StartInfo =
                                              {
                                                  FileName = @"c:\program files\7-zip\7z.exe",
                                                  Arguments = String.Format("t \"{0}\" -r", testfile),
                                                  UseShellExecute = false,
                                                  RedirectStandardOutput = true
                                              }
                                      };
                infoProcess.Start();
                var output = infoProcess.StandardOutput;
                var passed = false;
                while (output.EndOfStream == false)
                {
                    var line = output.ReadLine();
                    if (line != null && line.Contains("Everything is Ok"))
                    {
                        ConsolePlus.WriteLineGreen("{0} passed", testfile);
                        passed = true;
                    }
                    else if (line == null || line.Contains("failed"))
                    {
                        ConsolePlus.WriteLineRed("{0} failed", testfile);
                        passed = false;
                    }
                }
                var fileInfo = new FileInfo(testfile);
                if (passed)
                {
                    MoveFile(directory, fileInfo.Name, "passed");
                }
                else
                {
                    ConsolePlus.WriteLineRed("assuming failure... {0}", fileInfo.Name);
                    MoveFile(directory, fileInfo.Name, "failed");
                }
            }
        }

        private static void MoveFile(string directory, string fileName, string destinationDirectoryName)
        {
            var passedDirectory = Path.Combine(directory, destinationDirectoryName);
            if (!Directory.Exists(passedDirectory))
            {
                Directory.CreateDirectory(passedDirectory);
            }
            try
            {
                File.Move(Path.Combine(directory, fileName), Path.Combine(passedDirectory, fileName));
            }
            catch (IOException)
            {
                ConsolePlus.WriteLineRed("unable to move {0}", fileName);
            }
        }
    }
}
